﻿using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Threading;

namespace TestServer
{
    public static class Program
    {
        public const int PT_LIMIT = 255;
        private static void Main(string[] args)
        {
            Console.Title = "Stress-testing server";
            Console.WriteLine("Binding server at port 8081...");
            TcpListener srv = new TcpListener(new IPEndPoint(IPAddress.Loopback, 8081));
            PoolThreads = new List<Thread>(PT_LIMIT);
            srv.Start(PT_LIMIT);
            Console.WriteLine("Server started, pool threads/backlog limit: {0}", PT_LIMIT);
            Console.WriteLine();
            Console.WriteLine("Listen for incoming connections loop starts...");
            while (PoolThreads.Count <= PT_LIMIT)
            {
                ClearPool();
                TcpClient cli = srv.AcceptTcpClient();
                Console.WriteLine("Connected client at {0}", cli.Client.RemoteEndPoint.ToString());
                Thread t = new Thread(new ParameterizedThreadStart(ServerCommClient));
                PoolThreads.Add(t);
                Console.Title = "Stress-testing server - Pool overload: " + Overload(PoolThreads.Count) + "% (" + PoolThreads.Count.ToString() + "ts)";
                t.Start(cli);
            }
            srv.Stop();
            srv = null;
        }
        public static List<Thread> PoolThreads = null;
        public static void ServerCommClient(object t_arg)
        {
            TcpClient cli = (TcpClient)t_arg;

            Stream strm = cli.GetStream();
            byte[] bts = new byte[9999];
            strm.Read(bts, 0, cli.Available);
            string req = System.Text.Encoding.ASCII.GetString(bts);
            strm.Write(bts, 0, bts.Length);
            strm.Flush();
            cli.Close();
        }
        public static void ClearPool()
        {
            try
            {
                for (int i = 0; i < PoolThreads.Count; i++)
                {
                    if (PoolThreads[i] == null || ((Thread)(PoolThreads[i])).ThreadState == ThreadState.Stopped)
                        PoolThreads.RemoveAt(i);
                    i--;
                }
            }
            catch { }
        }
        public static int Overload(int ts)
        {
            return (int)((ts * 100) / (float)PT_LIMIT);
        }
    }
}
